package com.starsky.common.utils;

import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Method;
import java.util.*;

/**
 * @desc: List工具类
 * @author: wangsh
 */
public class ListUtils {

    /**
     * TODO list分页
     *
     * @param list
     * @param startIndex 开始位置
     * @param endIndex   结束位置
     * @return 返回分页后的List
     */
    public static List copy(List list, Integer startIndex, Integer endIndex) {
        if (list == null || list.size() <= 0) {
            return list;
        }
        if (startIndex == null || startIndex < 1) {
            startIndex = 1;
        }
        if (startIndex == null || startIndex < 1) {
            startIndex = 20;
        }
        if (startIndex > list.size()) {
            return new ArrayList();
        }
        if (endIndex > list.size()) {
            endIndex = list.size();
        }
        List ll = list;
        try {
            ll = list.subList(startIndex, endIndex);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ll;
    }

    /**
     * TODO list分页
     *
     * @param list
     * @param page 第几页
     * @param rows 每页显示多少
     * @return 返回分页后的List
     */
    public static List listPage(List list, Integer page, Integer rows) {
        if (list == null || list.size() <= 0) {
            return list;
        }
        if (page == null || page < 1) {
            page = 1;
        }
        if (rows == null || rows < 1) {
            rows = 20;
        }
        Integer start = (page - 1) * rows;
        Integer end = page * rows;

        if (start > list.size()) {
            return new ArrayList();
        }
        if (end > list.size()) {
            end = list.size();
        }
        List ll = list;
        try {
            ll = list.subList(start, end);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ll;
    }

    /**
     * @param list 待排序数据,排序完成后,同时存放在该list里面
     * @param map  存放排序规则
     * @Description: TODO 支持多字段排序,map存放要排序的字段名称以及要排序的方式,key为字段名称,value为排序方式(DESC或者ASC)
     * 注意:
     * 1.该处存在优先关系,遵循先入为主原则,即先根据第一个比较,如果相等再比较第二个,以此类推
     * 2.暂时只针对Map<String, Object>数组和实体对象数组进行排序
     * <p>
     * 具体可以查看  ListUtilTest
     */
    public static void sort(List<?> list, final LinkedHashMap<String, String> map) {
        if (list != null && list.size() > 0) {
            Collections.sort(list, new Comparator() {
                public int compare(Object arg1, Object arg2) {
                    if (arg1 == null && arg2 == null) {
                        // 如果两个同时为null,则判断两个相等
                        return 0;
                    } else if (arg1 == null) {
                        // 如果第一个为null,则判断第一个小
                        return -1;
                    } else if (arg2 == null) {
                        // 如果第二个为null,则判断第二个小
                        return 1;
                    } else if (arg2 != arg1 && null != arg2) {
                        try {
                            Object o1 = null;
                            Object o2 = null;
                            for (String sortField : map.keySet()) {
                                if (arg1 instanceof Map) {
                                    Map<String, Object> obj1 = (Map<String, Object>) arg1;
                                    Map<String, Object> obj2 = (Map<String, Object>) arg2;
                                    o1 = obj1.get(sortField);
                                    o2 = obj2.get(sortField);
                                } else {
                                    // 首字母转大写
                                    String newStr = sortField.substring(0, 1).toUpperCase() + sortField.replaceFirst("\\w", "");
                                    String methodStr = "get" + newStr;
                                    // 创建两个实体的get方法
                                    Method method1 = arg1.getClass().getMethod(methodStr, null);
                                    Method method2 = arg2.getClass().getMethod(methodStr, null);
                                    o1 = method1.invoke(arg1, null);
                                    o2 = method2.invoke(arg2, null);
                                }
                                int compareRes = compareByType(o1, o2);
                                if (compareRes != 0) {
                                    if (map.get(sortField) != null && map.get(sortField).equalsIgnoreCase("asc")) {
                                        // 如果排序字段是正序,则要乘上负一
                                        return -compareRes;
                                    } else {
                                        // 如果排序字段是倒序,则直接返回
                                        return compareRes;
                                    }
                                } else {
                                    continue;
                                }
                            }
                            return compareByType(o1, o2);
                        } catch (Exception e) {
                            throw new RuntimeException();
                        }
                    } else {
                        return -1;
                    }
                }

            });
        }
    }

    /**
     * @param obj1 比较的第一个
     * @param obj2 比较的第二个
     * @Description: TODO 两个值的比较方法,如果第一个比第二个大,则返回1,相等返回0,第一个比第二个小返回-1
     */
    private static int compareByType(Object obj1, Object obj2) {
        int retVal = 0;
        if (null == obj1 && null == obj2) {
            // 如果两个同时为null,则判断两个相等
            return retVal;
        }
        if (null == obj1) {
            // 因为是倒序,所以如果第一个为null,则第一个大
            return 1;
        }
        if (null == obj2) {
            // 因为是倒序,如果第二个为null,则第二个大
            return -1;
        }
        // 默认倒序
        if (obj2 instanceof Integer) {
            retVal = ((Integer) obj2).compareTo((Integer) obj1);
        } else if (obj2 instanceof Date) {
            // 日期
            retVal = ((Date) obj2).compareTo((Date) obj1);
        } else if (obj2 instanceof Double) {
            retVal = ((Double) obj2).compareTo((Double) obj1);
        } else if (obj2 instanceof Long) {
            retVal = ((Long) obj2).compareTo((Long) obj1);
        } else if (obj2 instanceof Float) {
            retVal = ((Float) obj2).compareTo((Float) obj1);
        } else {
            // 长度相等时比较ASCII值
            retVal = obj2.toString().compareTo(obj1.toString());
        }
        return retVal;
    }

    public static void asc(List<?> list, String sort) {
        desc(list, sort);
        Collections.reverse(list);
    }

    public static void sort(List<?> list, final String sortField, final String sortMode) {
        if (StringUtils.isNotEmpty(sortMode) && sortMode.equalsIgnoreCase("desc")) {
            desc(list, sortField);
        } else {
            asc(list, sortField);
        }
    }

    /**
     * @param targetList 目标排序List
     * @param sortField  排序字段(实体类属性名,或者Map的字段名)
     * @ 排序方式(asc or desc)
     */
    @SuppressWarnings({"unchecked", "rawtypes"})
    public static void desc(List<?> targetList, final String sortField) {
        try {
            if (targetList != null && targetList.size() > 0) {
                Collections.sort(targetList, new Comparator() {
                    public int compare(Object arg1, Object arg2) {
                        if (arg1 == null && arg2 == null) {
                            // 如果两个同时为null,则判断两个相等
                            return 0;
                        } else if (arg1 == null) {
                            // 如果第一个为null,则判断第一个小
                            return -1;
                        } else if (arg2 == null) {
                            // 如果第二个为null,则判断第二个小
                            return 1;
                        } else if (arg2 != arg1 && null != arg2) {
                            try {
                                Object o1 = null;
                                Object o2 = null;
                                if (arg1 instanceof Map) {
                                    Map<String, Object> obj1 = (Map<String, Object>) arg1;
                                    Map<String, Object> obj2 = (Map<String, Object>) arg2;
                                    o1 = obj1.get(sortField);
                                    o2 = obj2.get(sortField);
                                } else {
                                    // 首字母转大写
                                    String newStr = sortField.substring(0, 1).toUpperCase() + sortField.replaceFirst("\\w", "");
                                    String methodStr = "get" + newStr;
                                    // 创建两个实体的get方法
                                    Method method1 = arg1.getClass().getMethod(methodStr, null);
                                    Method method2 = arg2.getClass().getMethod(methodStr, null);
                                    o1 = method1.invoke(arg1, null);
                                    o2 = method2.invoke(arg2, null);
                                }
                                return compareByType(o1, o2);
                            } catch (Exception e) {
                                throw new RuntimeException();
                            }
                        } else {
                            return -1;
                        }
                    }

                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * @param list
     * @return void 返回类型
     * @throws
     * @Description:去除重复元素,需要重写hashcode(),equals()方法
     */
    public static List removeDuplicate(List list) {
        if (list != null && list.size() > 0) {
            HashSet h = new HashSet(list);
            list.clear();
            list.addAll(h);
        }
        return list;
    }

    /**
     * @param list
     * @return void 返回类型
     * @throws
     * @Description:去除重复元素数量,需要重写hashcode(),equals()方法
     */
    public static int removeDuplicateTotal(List<?> list) {
        int count = 0;
        if (list != null && list.size() > 0) {
            int total = list.size();
            HashSet h = new HashSet(list);
            list.clear();
            list.addAll(h);
            count = total - list.size();
        }
        return count;
    }

    /**
     * 判断集合是否为空，是否小于等于0
     *
     * @param resList
     * @return
     */
    public static boolean isEmpty(Map resList) {
        return !isNotEmpty(resList);
    }

    /**
     * 判断集合是否为空，是否大于0
     *
     * @param map
     * @return
     */
    public static boolean isNotEmpty(Map map) {
        if (map != null && map.size() > 0) {
            return true;
        }
        return false;
    }


    /**
     * 判断集合是否为空，是否小于等于0
     *
     * @param resList
     * @return
     */
    public static boolean isEmpty(List resList) {
        return !isNotEmpty(resList);
    }

    /**
     * 判断集合是否为空，是否大于0
     *
     * @param resList
     * @return
     */

    public static boolean isNotEmpty(List resList) {
        if (resList != null && resList.size() > 0) {
            return true;
        }
        return false;
    }

}
